package com.nuoniu.sibanyun.service.erp.barcode.impl;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.entity.dto.BarcodeMainInfoSearchDto;
import com.nuoniu.sibanyun.entity.dto.ErpBarcodeInOutSaveDto;
import com.nuoniu.sibanyun.entity.dto.WorkProcedureReportDto;
import com.nuoniu.sibanyun.entity.erp.ErpProcessRouteDetail;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpBarcodeInOut;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpBarcodeMainInfo;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpBarcodeProcessReport;
import com.nuoniu.sibanyun.entity.erp.in.InWarehouse;
import com.nuoniu.sibanyun.entity.so.VAreaCalculationDetail;
import com.nuoniu.sibanyun.entity.so.VAreaCalculationMain;
import com.nuoniu.sibanyun.entity.vo.WorkProcedureReportResult;
import com.nuoniu.sibanyun.mapper.erp.barcode.ErpBarcodeProcessReportMapper;
import com.nuoniu.sibanyun.service.erp.IErpAccountService;
import com.nuoniu.sibanyun.service.erp.IErpProcessRouteDetailService;
import com.nuoniu.sibanyun.service.erp.barcode.IErpBarcodeInOutService;
import com.nuoniu.sibanyun.service.erp.barcode.IErpBarcodeMainInfoService;
import com.nuoniu.sibanyun.service.erp.barcode.IErpBarcodeProcessReportService;
import com.nuoniu.sibanyun.service.erp.in.IInWarehouseService;
import com.nuoniu.sibanyun.service.so.IVAreaCalculationDetailService;
import com.nuoniu.sibanyun.service.so.IVAreaCalculationMainService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 条码工序汇报记录 服务实现类
 * </p>
 *
 * @author 白强
 * @since 2021-11-27
 */
@Service
@Log4j2
public class ErpBarcodeProcessReportServiceImpl extends ServiceImpl<ErpBarcodeProcessReportMapper, ErpBarcodeProcessReport> implements IErpBarcodeProcessReportService {

    @Autowired
    private IErpProcessRouteDetailService processRouteDetailService;
    @Autowired
    private IErpBarcodeMainInfoService barcodeMainInfoService;
    @Autowired
    private IErpAccountService erpAccountService;
    @Autowired
    private IInWarehouseService inWarehouseService;
    @Autowired
    private IErpBarcodeInOutService barcodeInOutService;
    @Autowired
    private IVAreaCalculationMainService areaCalculationMainService;
    @Autowired
    private IVAreaCalculationDetailService areaCalculationDetailService;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public WorkProcedureReportResult batchSaveCardDetail(WorkProcedureReportDto workProcedureReportDto) {
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        /** 工艺路线明细ID */
        Integer erpProcessRouteDetailId = workProcedureReportDto.getErpProcessRouteDetailId();
        ErpProcessRouteDetail processRouteDetail = processRouteDetailService.getById(erpProcessRouteDetailId);
        Integer workOrder = processRouteDetail.getWorkOrder();
        Integer workFlag = processRouteDetail.getWorkFlag();
        if(null == processRouteDetail)throw new NuoNiuException("汇报工序失败，查询不到工艺明细");
        UserInfo userInfo = UserThreadLocal.get();
        LocalDateTime now = LocalDateTime.now();
        WorkProcedureReportResult reportResult = new WorkProcedureReportResult();
        /** 1. 条码 解析*/
        BarcodeMainInfoSearchDto barcodeMainInfoSearchDto = new BarcodeMainInfoSearchDto();
        barcodeMainInfoSearchDto.setBarcode(workProcedureReportDto.getBarcodeStr());
        List<ErpBarcodeMainInfo> erpBarcodeMainInfoList = barcodeMainInfoService.analysisByBarCode(barcodeMainInfoSearchDto);
        if(erpBarcodeMainInfoList.size() == 0)throw new NuoNiuException("无效条码");
        /** 校验 条码 是否 来自  加工单明细 （无效条码）*/
        String[] split = workProcedureReportDto.getBarcodeStr().split(",");
        List<String> orgBarcodes = new ArrayList<>(Arrays.asList(split));
        List<String> matchBarcodes = erpBarcodeMainInfoList.stream().filter(f -> f.getSourceVoucherType().equals("AreaCalculation")).map(ErpBarcodeMainInfo::getBarCode).collect(Collectors.toList());
        orgBarcodes.removeAll(matchBarcodes);
        reportResult.setNotMatchCodes(orgBarcodes);
        List<String> failMatchCodes = new ArrayList<>();
        List<String> successMatchCodes = new ArrayList<>();
        reportResult.setFailMatchCodes(failMatchCodes);
        reportResult.setSuccessMatchCodes(successMatchCodes);

        /** 2. 查询 源单据 数据*/
        for (ErpBarcodeMainInfo item : erpBarcodeMainInfoList) {
            String barCode = item.getBarCode();
            try {
                ErpBarcodeProcessReport newErpBarcodeProcessReport = new ErpBarcodeProcessReport();
                // 获取 源单明细id
                Integer sourceDetailId = item.getSourceDetailId();
                // 查询 当前 条码汇报最新记录
                ErpBarcodeProcessReport lastBarcodeReport = baseMapper.getLastBarcodeReport(userInfo.getCompanyId(), barCode);
                if (null != lastBarcodeReport) {
                    Integer processRouteId = lastBarcodeReport.getProcessRouteId();
                    String processRouteName = lastBarcodeReport.getProcessRouteName();
                    /**  校验 当前工艺路线 是否 是*/
                    if(!processRouteId.equals(processRouteDetail.getPrId()))throw new NuoNiuException("工序汇报错误：工艺路线不匹配，当前条码请选择：" + processRouteName);
                    Integer nextProcedureOrder = lastBarcodeReport.getNextProcedureOrder();
                    String nextProcedureName = lastBarcodeReport.getNextProcedureName();
                    if(null == nextProcedureOrder)throw new NuoNiuException("工序汇报错误：所有工序已经汇报完毕");
                    if (null != nextProcedureOrder && workOrder.compareTo(nextProcedureOrder) > 0)
                        throw new NuoNiuException("工序汇报错误：请汇报：" + nextProcedureName + " 工序");
                    if (null != nextProcedureOrder && workOrder.compareTo(nextProcedureOrder) < 0) throw new NuoNiuException("当前工序已经汇报过了");

                } else {
                    if (workOrder > 1) {
                        //查询 首工序
                        ErpProcessRouteDetail firstOrderDetail = processRouteDetailService.getFirstOrderDetail(processRouteDetail.getPrId());
                        String workName = firstOrderDetail.getWorkName();
                        throw new NuoNiuException("请汇报首工序：" + workName);
                    }
                    //校验 工艺路线 是否 匹配

                }
                /** 组装工序汇报*/
                newErpBarcodeProcessReport.setCompanyId(userInfo.getCompanyId());
                newErpBarcodeProcessReport.setAccountId(currentAccountId);
                newErpBarcodeProcessReport.setBarcode(barCode);
                newErpBarcodeProcessReport.setProcedureName(processRouteDetail.getWorkName());
                newErpBarcodeProcessReport.setProcedureOrder(processRouteDetail.getWorkOrder());
                newErpBarcodeProcessReport.setProcedureFlag(processRouteDetail.getWorkFlag());
                newErpBarcodeProcessReport.setReportTime(now);
                newErpBarcodeProcessReport.setReportUserId(userInfo.getUserId());
                newErpBarcodeProcessReport.setReportUserName(userInfo.getRealName());
                newErpBarcodeProcessReport.setProcedureId(processRouteDetail.getWorkId());
                newErpBarcodeProcessReport.setProcessRouteDetailId(processRouteDetail.getId().intValue());
                newErpBarcodeProcessReport.setProcessRouteId(processRouteDetail.getPrId());
                newErpBarcodeProcessReport.setSourceDetailId(sourceDetailId);
                newErpBarcodeProcessReport.setSourceVoucherId(item.getSourceVoucherId());
                newErpBarcodeProcessReport.setSourceVoucherCode(item.getSourceVoucherCode());
                newErpBarcodeProcessReport.setSourceVoucherType(item.getSourceVoucherType());
                newErpBarcodeProcessReport.setSourceVoucherDate(item.getSourceVoucherDate());
                if (workFlag != 2) {
                    ErpProcessRouteDetail nextOrderDetail = processRouteDetailService.getNextOrderDetail(processRouteDetail.getPrId(), processRouteDetail.getWorkOrder());
                    if (null != nextOrderDetail) {
                        newErpBarcodeProcessReport.setNextProcedureId(nextOrderDetail.getWorkId());
                        newErpBarcodeProcessReport.setNextProcedureName(nextOrderDetail.getWorkName());
                        newErpBarcodeProcessReport.setNextProcedureOrder(nextOrderDetail.getWorkOrder());
                        newErpBarcodeProcessReport.setNextProcedureFlag(nextOrderDetail.getWorkFlag());
                    }
                }
                /** 保存 条码更新汇报记录 */
                boolean b = save(newErpBarcodeProcessReport);
                /** 如果是尾工序 自动入库*/
                if (b && workFlag == 2) {
                    //1.查询 默认仓库 todo 设置默认 仓库
                    List<InWarehouse> inWarehouses = inWarehouseService.listCompanyInWarehouses(null);
                    if (inWarehouses.size() == 0){
                        barCode += "：汇报成功，但未入库，没有设置仓库";
                    }else {
                        InWarehouse inWarehouse = inWarehouses.get(0);
                        ErpBarcodeInOutSaveDto erpBarcodeInOutSaveDto = new ErpBarcodeInOutSaveDto();
                        erpBarcodeInOutSaveDto.setType(1);
                        erpBarcodeInOutSaveDto.setSourceDetailId(sourceDetailId);
                        erpBarcodeInOutSaveDto.setSourceVoucherId(item.getSourceVoucherId());
                        erpBarcodeInOutSaveDto.setSourceVoucherType("AreaCalculation");
                        erpBarcodeInOutSaveDto.setBarcode(barCode);
                        erpBarcodeInOutSaveDto.setWarehouseId(inWarehouse.getId().intValue());
                        erpBarcodeInOutSaveDto.setWarehouseCode(inWarehouse.getWhCode());
                        erpBarcodeInOutSaveDto.setWarehouseName(inWarehouse.getWhName());
                        barcodeInOutService.saveErpBarcodeInOut(erpBarcodeInOutSaveDto);
                        /** 更新批次完成数量（面积计算表 主表 累计执行数量）  */
                        VAreaCalculationDetail areaCalculationDetail = areaCalculationDetailService.getById(sourceDetailId);
                        areaCalculationMainService.updateCumExecuteQuantity(areaCalculationDetail.getOrderId().longValue(), BigDecimal.ONE);

                    }
                }
                successMatchCodes.add(barCode);
            } catch (Exception e) {
                String msg = "";
                if (e instanceof NuoNiuException) {
                    msg = ((NuoNiuException) e).getMsg();
                } else {
                    msg = "汇报失败！";
                    log.info(msg+""+e.getMessage());
                    e.printStackTrace();
                }
                failMatchCodes.add(barCode + ": " + msg);
            }

        }
        return reportResult;
    }
}
